import { app, ipcMain, BrowserWindow,globalShortcut,protocol,nativeTheme,screen,session,webContents } from 'electron'
import {autoUpdater} from 'electron-updater'
// const windowStateKeeper = require('electron-window-state');
const { exec } = require('child_process');
const net = require('net'); 
//win 多屏
// const WindowManager = require('electron-windows');
// const { exec } = require('child_process');
// const net = require('net'); 
import AutoLaunch from "easy-auto-launch";
import { join } from 'node:path'
import updateHandle from './update'  
const fs = require("fs");
const fspromises = require('fs').promises;
const path = require('path')
const Store = require('electron-store');
const md5 = require('md5');
const os = require('os');
const log = require("electron-log")
log.transports.file.maxSize = 1048576;
log.transports.console.level = 'silly'; 
let option={
    name:"config",//文件名称,默认 config
    fileExtension:"json",//文件后缀,默认json
    cwd:app.getPath('userData'),//文件位置,尽量不要动，默认情况下，它将通过遵循系统约定来选择最佳位置。C:\Users\xxx\AppData\Roaming\my-electron\config.json
//    encryptionKey:"aes-256-cbc" ,//对配置文件进行加密
    clearInvalidConfig:true, // 发生 SyntaxError  则清空配置,
}
const  store = new Store(option);  
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
process.env.DIST_ELECTRON = join(__dirname, '..')
// process.env.DIST_ELECTRON = join(app.getAppPath() , '..')
process.env.DIST = join(process.env.DIST_ELECTRON, '../dist')
process.env.PUBLIC = process.env.VITE_DEV_SERVER_URL
  ? join(process.env.DIST_ELECTRON, '../public')
  : process.env.DIST 

const url = process.env.VITE_DEV_SERVER_URL
const indexHtml = join(process.env.DIST, 'index.html')
const shortcut = { 
  FullScreen: process.platform === 'darwin' ? 'CmdOrCtrl+F' : 'F11',
  DevTools: process.platform === 'darwin' ? 'CmdOrCtrl+I' : ' ctrl+F12',  
  reload: process.platform === 'darwin' ? 'CmdOrCtrl+R' : ' ctrl+F4',
};
///////Server
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const server = express();
/////
///unzip
var unzip = require("node-unzip-2")
export const updateAutoLaunch = async (isAutoLaunchEnabled: boolean = true) => {
  if (process.platform === "linux") {
    const autoLauncher = new AutoLaunch({
        name: app.getName(),
        isHidden: false,
        path: process.env.APPIMAGE
    });

    if (isAutoLaunchEnabled) {
        await autoLauncher.enable();
    } else {
        await autoLauncher.disable();
    } 
  }
}
////////////////////自启动//////////////
//注意：非开发环境
// if (app.isPackaged) {
//   const appFolder = path.dirname((process.execPath))
//   const updateExe = path.resolve(appFolder, 'parkviews.exe')
//   const exeName = path.basename(process.execPath) 
//   // log.info(updateExe);
//   //linux开机自动重启
//   updateAutoLaunch();
//   if (process.platform === "darwin") {
//     app.setLoginItemSettings({
//       openAtLogin: true,//是否开机启动
//       openAsHidden: true//是否隐藏主窗体，保留托盘位置
//     });
//   } else { 
//     app.setLoginItemSettings({
//       openAtLogin: true,
//       openAsHidden: true,
//       path: updateExe,
//       args: [
//         "--processStart",
//         `"${exeName}"`,
//         "--process-start-args",
//         `"--hidden"`
//       ]
//     });
//   }
// } 

////////////自启动////////////////
let serverPort=9999;
let win: BrowserWindow | null = null;
//设备信息
let appInfo:any = null;
//用户信息
let userInfo:any = null;
//license
let license:any = null;
async function initData(){
  let mac = null;
  if(os.networkInterfaces().WLAN){
    mac = os.networkInterfaces().WLAN[0].mac
  }else if(!mac&&os.networkInterfaces()['以太网']){
    mac = os.networkInterfaces()['以太网'][0].mac
  }else if(!mac&&os.networkInterfaces()['en0']){
    mac = os.networkInterfaces()['en0'][0].mac
  }  
  let str=`${os.platform()}${os.arch()}${mac}${os.totalmem()}}`
  const uniqueId = md5(str); 
  let version=app.getVersion(); 
  appInfo={id:uniqueId,mac:mac,platform:os.platform(),arch:os.arch(),
    mem:os.totalmem(),version:version,dateline:new Date().getTime,
    isPackaged:app.isPackaged,env:process.env.NODE_ENV}
  if(store.get('appInfo.id')){ 
    store.delete('appInfo');
  }
  if(store.get('userInfo.id')){ 
    userInfo=store.get('userInfo');
  }
  store.set('appInfo', appInfo); 
  let port=store.get('ServerPort');
  if(!port){
    serverPort= port;
  }
  if(store.get('Offline')){
    initServer(serverPort);
  }
  //license 
  license=store.get('License');
}

async function initServer(serverPort:any){
    // 启用 CORS
  server.use(cors());

  // server.use(express.static("public"));
  server.use(express.static(join(app.getPath('userData'), "Project")));
  // 解析 JSON 请求体
  server.use(bodyParser.json());
  server.use(bodyParser.urlencoded({ extended: true }));

  // 设置路由（根据需要添加）
  server.get('/', (req, res) => {
      res.send('Parkview ok!');
  });

  // 启动服务器并监听端口（根据需要更改端口号）
  server.listen(serverPort, () => {
      console.log('Server started on port ${serverPort},http://localhost:${serverPort}');
  }); 
}

initData();
let winList=[];
const createWindow = () => { 
    // let mainWindowState = windowStateKeeper({
    //   defaultWidth: 1920,
    //   defaultHeight: 1080
    // }); 

    win = new BrowserWindow({ 
      webPreferences: {
        // isolatedWord:true,
        // isolatedWordId:1,
        // isolateInsgentProcess:true,
        user:true,
        allowRunningInsecureContent: true,
        contextIsolation: true, // 是否开启隔离上下文
        nodeIntegration: true, // 渲染进程使用Node API
        webSecurity: false,
        preload: join(__dirname, '../preload.js'),
        webviewTag:true,
        partition:"persist:parkview-win", 
      },
      x: 0,
      y: 0,
      width: 1920,
      height: 1080,
    });  
    // mainWindowState.manage(win)

    const winStore = new Store({
      name: 'window-state',
      cwd: app.getPath('userData'), // 使用窗口ID作为存储的目录
      fileExtension: 'json'
    }); 
    // 将存储实例关联到窗口
    win.winStore = winStore;
     console.log(indexHtml)
  // 如果打包了，渲染index.html
  if (app.isPackaged) {
    // win?.setFullScreen(true);
    // win?.setMenuBarVisibility(false);
    win.loadFile(indexHtml);
    log.info(indexHtml)
    // win.loadURL("http://www.codeforest.cn")
    // win.webContents.openDevTools()
  } else {
    // win?.setFullScreen(true);
    // win?.setMenuBarVisibility(false);
    win.loadURL(url)
    win.webContents.openDevTools()
  }
   

  // if (process.env.VITE_DEV_SERVER_URL) { // electron-vite-vue#298
  //   win.loadURL(url)
  //   // Open devTool if the app is not packaged
  //   win.webContents.openDevTools()
  // } else {
  //   win.loadFile(indexHtml)
  // }
    // 当窗口关闭时释放 windowState
    win.on('closed', () => {
      win = null;
      // mainWindowState.saveState();
    });
    // 自定义元素拖动
    // win.webContents.on('did-finish-load', () => {
    //   win.webContents.executeJavaScript(`
    //     document.getElementById('draggable').addEventListener('mousedown', function(e) {
    //       e.preventDefault();
    //       let offsetX = e.clientX - this.getBoundingClientRect().left;
    //       let offsetY = e.clientY - this.getBoundingClientRect().top;
    //       document.addEventListener('mousemove', moveHandler);
    //       function moveHandler(e) {
    //         window.getCurrentWindow().setBounds({
    //           x: e.screenX - offsetX,
    //           y: e.screenY - offsetY
    //         });
    //       }
    //       document.addEventListener('mouseup', function() {
    //         document.removeEventListener('mousemove', moveHandler);
    //       });
    //     });
    //   `);
    // });
  
  globalShortcut.register(shortcut.reload, () => {
    win?.reload();
  });
  // globalShortcut.register("ctrl+F6", () => {
  //   app.exit();
  // });
  globalShortcut.register(shortcut.FullScreen, () => {
    // 是否全屏
    if (win?.isFullScreen()) {
      // this.mainWindow?.minimize();
      win?.setFullScreen(false);
      win?.setMenuBarVisibility(true);
    } else {
      win?.setFullScreen(true);
      win?.setMenuBarVisibility(false);
    }
  });
  globalShortcut.register(shortcut.DevTools, () => {
    win?.webContents.openDevTools({ mode: "detach" }); 
  });
  //隐藏菜单栏
  win?.setMenu(null) 
  // 尝试更新, 只有当用户第一次打开app时才触发 
  // win.webContents.on("did-finish-load",()=>{
  //   updateHandle(win)
  // })

  // win.webContents.on("did-finish-load",()=>{
  //   // win.webContents.send('getAppInfo',JSON.stringify(appInfo))
  // })
  updateHandle(win);

  win.setAspectRatio(1920/1080)
  win?.on('resize', () => { 
    const winBounds = win?.getBounds();
    win?.webContents.send('winChangeEvent',winBounds)
  });  

  win.webContents.on('did-frame-finish-load', () => {
    const webview = win.getBrowserViews()[0];
    if (webview) {
      webview.setUserAgent("winClient="+appInfo.id);
    }
  });
   //===========自定义file:///协议的解析=======================
  //  protocol.interceptFileProtocol('file', (req, callback) => {
  //   const url = req.url.substr(8);
  //   callback(decodeURI(url));
  // }, (error) => {
  //   if (error) {
  //     console.error('Failed to register protocol');
  //   }
  // }); 
  //监听下载
  win.webContents.session.on("will-download", 
  (event, item, webcontent) => {
    let directory= join(app.getPath('userData'), 'Project',"themeSite",item.getFilename())
    console.log(item.getURL()) 
    console.log(directory) 
    let url=item.getURL();
    //设置下载文件名 工程项目下载
    if(url.indexOf("blob:")>=0){
      item.setSavePath(directory)
      item.on('updated', (event, state) => {
        // 下载的事件
        if (state === "progressing") {
          if (!item.isPaused()) {
          //下载完成后传回进度
          win?.webContents.send("downing", 
            item.getReceivedBytes() * 100 / item.getTotalBytes())
          }
        }
      })
      item.once('done', (event, state) => {
        // 下载完成的事件
        if (state === "completed") {
          //下载完成后传回进度
          win?.webContents.send("downing", 100)
  
          fs.createReadStream(directory).pipe(unzip.Extract({ path: directory.replace(".zip","") }))  //解压时直接会覆盖重名文件
        }
      })
    } 
  }) 
  winList.push(win)
};

//win 多屏
// const windowManager = new WindowManager();
// function createOtherWin(option:any){
//   const otherWindow = windowManager.create({
//     name: 'win-parkviews'+option.id, 
//     browserWindow: { 
//       // displayBounds:{
//         x: option.x,
//         y: option.y,
//       // },
//       width: 1920,
//       height: 1080,
//       titleBarStyle: 'hidden',
//       show: true,
//       webPreferences: {
//         // isolatedWord:true,
//         // isolateInsgentProcess:true,
//         // isolatedWordId:option.id,
//         allowRunningInsecureContent: true,
//         contextIsolation: true, // 是否开启隔离上下文
//         nodeIntegration: true, // 渲染进程使用Node API
//         webSecurity: false,
//         preload: join(__dirname, '../preload.js'),
//         webviewTag:true,
//         partition:"persist:parkview-win+"+option.id
//       },
//     }, 
//     openDevTools: !app.isPackaged,
//     // storageKey: 'storage-filename'+option.id, // optional. The name of file. Support storage of window state
//     // storagePath: app.getPath('userData'), // optional. The path of file, only used when storageKey is not empty 
//   });   
 
//    // 如果打包了，渲染index.html
//    if (app.isPackaged) {
//     otherWindow?.setFullScreen(true);
//     otherWindow?.setMenuBarVisibility(false);
//     otherWindow.loadURL(indexHtml);
//     // win.webContents.openDevTools()
//   } else {
//     otherWindow?.setFullScreen(true);
//     otherWindow?.setMenuBarVisibility(false);
//     otherWindow.loadURL(url)
//     otherWindow.webContents.openDevTools()
//   }
//   winList.push(otherWindow) 
// } 

const gotTheLock = app.requestSingleInstanceLock();
 
if (!gotTheLock) {
  app.quit();
} else {
  app.on('second-instance', (event, commandLine, workingDirectory) => {
    // 当尝试再次打开应用程序时，将焦点回到主窗口
    if (win) {
      if (win.isMinimized()) win.restore();
      win.focus();
    }
  });
 
  app.on('ready', () => {
    createWindow()
    // 其余窗口创建和主进程逻辑
  });
 
  app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
      app.quit();
    }
  });
}


app.whenReady().then(() => {
  // const webReqFilter = {
  //     urls: ['*://*/*']
  // }
  app.commandLine.appendSwitch('ignore-certificate-errors')
  // // protocol.interceptFileProtocol
  // session.defaultSession.webRequest.onBeforeRequest(webReqFilter, function(details, callback){
  //     console.log('webRequest.onBeforeRequest', details);
  //     // callback({ cancel: false, redirectURL: 'https://cn.bing.com/'});
  //     callback({});
  // });

  // // Returns Boolean - Whether the protocol was successfully intercepted
  // protocol.interceptFileProtocol('file', function(request, callback, next){
  //     console.log('protocol.interceptFileProtocol', request);
  //     // callback({ statusCode: 400, data: 'Host Not Allowed' });
  //     // const url = request.url.substr(8);
  //     // var fPath = `file://${__dirname}/dist/index.html`;
  //     // var fPath = request.url.substr(8);  // 截取file:///之后的内容，也就是我们需要的
  //     // if(fPath.indexOf('element-icons') >= 0 && fPath.indexOf('.woff') >= 0) fPath = gElementIconsWoff;
  //     // if(fPath.indexOf('element-icons') >= 0 && fPath.indexOf('.ttf') >= 0) fPath = gElementIconsTtf;

  //     // fPath = path.normalize(fPath);
  //     // console.log('protocol.interceptFileProtocol', fPath)
  //     // callback({ path: fPath});
  //     return true;

  // }); 
  // if(!win){ 
  //   createWindow()
  // }
  //win 多屏
  // if(store.get('AllDisplays')){ 
  //     // 判断当前的窗口数量
  //     let displays = screen.getAllDisplays() 
  //     // 判断是否副窗口
  //     let externalDisplay = displays.find((display) => {
  //       if(display.bounds.x !== 0 || display.bounds.y !== 0){
  //         // createOtherWin({id:display.id, x: display.bounds.x, y: display.bounds.y}); // 创建窗口 
  //       }
  //     }) 
  //     // 如果是副窗口 
  // } 
  // app.on('activate', () => {
  //   // if (BrowserWindow.getAllWindows().length === 0) {
  //     createWindow();
  //   // }
  // });
  protocol.registerFileProtocol('file', (request, callback) => {
    console.log(request)
  	//截取file:///之后的内容，也就是我们需要的
    const url = request.url.substr(8)
    //使用callback获取真正指向内容
    callback({ path: path.normalize(`${__dirname}/${url}`) })
  }, (error) => {
    if (error) console.error('Failed to register protocol')
  })
});  

app.on('ready', async () => { 
  // 设置数据
  global.sharedObject = {
    appInfo
  }
  //py 
  // startServer_EXE();
  // startServer_PY();
});
// 关闭窗口
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    //关闭python
    try {
      stopServer()
    } catch (error) {} 
    try {
      server.close()
    } catch (error) {} 
    app.quit();
  } 
}); 

async function getWinInfo() {
  return win.getBounds();
}
ipcMain.handle('win:info', getWinInfo) 
//获取app的信息
async function getAppInfo() {
  return JSON.stringify(appInfo);
}
ipcMain.handle('app:info', getAppInfo) 
//获取用户的信息
async function getUserInfo() {
  console.log(userInfo);
  return JSON.stringify(userInfo);
}
ipcMain.handle('user:info', getUserInfo)
ipcMain.on('user:set', function(event,data){
  console.log(userInfo);
  store.delete('userInfo');
  store.set('userInfo', data); 
  userInfo=data;
});
async function getLicense() {
  return license;
}
ipcMain.handle('license:info', getLicense)
ipcMain.on('license:set', function(event,data){
  Object.keys(data).forEach(key => { 
     //设置最新的配置
     if(key=='License'){
      license=data[key]
    }
    if(key!='appInfo'){
      let user=store.get('userInfo')
      if(key=='orgId'||key=='apiHost'){
        if(!user){
          user={};
        }
        console.log(user)
        if(store.get('userInfo.id')){ 
          store.delete('userInfo');
        }
        user[key]=data[key];
        store.set('userInfo', user); 
      }else{
        if(store.get(key)){ 
          store.delete(key);
        }
        store.set(key, data[key]); 
      }  
    }
  })   
});

async function getUserDataPath() { 
  return app.getPath('userData')
}

const publicFilePath = join(process.env.PUBLIC, '') 
//清理缓存
ipcMain.handle('clearCache', function(event){  
  try {
    const cachePath =  join(app.getPath('userData'), 'Cache',"Cache_Data")
    if (fs.existsSync(cachePath)) {
      const files = fs.readdirSync(cachePath);
      files.forEach(function(file) {
        const curPath = path.join(cachePath, file);
        fs.unlinkSync(curPath);
      });
    }
  } catch (error) {
    
  }
  app.relaunch(app.isPackaged?process.execPath:__dirname);
  app.quit();
}); 
ipcMain.handle('reloadWin', function(event){ 
  win?.reload();
}); 
ipcMain.handle('filePath:info', function(event,data){ 
  return fs.readFileSync(join(publicFilePath, data), "utf-8")
}); 
ipcMain.handle('tempFilePath:info', function(event,url){ 
  return fs.readFileSync(join(app.getPath('userData'), url), "utf-8")
}); 
ipcMain.handle('getTempFilePath', getUserDataPath); 
ipcMain.on('tempFilePath:set', function(event,url,data){ 
  fs.writeFileSync(join(app.getPath('userData'), url), JSON.stringify(data));
}); 
//主题设置
ipcMain.on('nativeTheme:set', function(event,data){
  nativeTheme.themeSource=data; 
}); 
async function readDirectory(directory:any) {
  let projectList=[];
  try {
    const files = await fspromises.readdir(directory);
    for (const file of files) {
      const filePath = path.join(directory, file);
      const stats = await fspromises.stat(filePath);
      if (stats.isDirectory()) {
        console.log(filePath)
        // await readDirectory(filePath); // 递归调用
        let str= await fspromises.readFile(filePath+"/config.json", "utf-8") 
        let project=JSON.parse(str)
        project.screens=[]
        projectList.push(project)
        console.log(project);   
      } else {
        console.log(filePath); // 处理文件
      }
    }
  } catch (error) {
    console.error(error);
  }
  return projectList
}
async function getLocalProject() { 
  let path= join(app.getPath('userData'), 'Project',"themeSite")
  let projectList = await readDirectory(path); 
  return projectList;
 }

 ipcMain.handle('getLocalProject', getLocalProject); 
 ipcMain.handle('getLocalServer', function(){
  return "http://localhost:"+serverPort;
 }); 
////全局消息
ipcMain.on('winAllMessage', function(event,data){
  log.info(data)
  for (let index = 0; index < winList.length; index++) {
   const element = winList[index]; 
  //  setTimeout(() => {
  //   element?.webContents.send('pageMessage', data);
  //  },500); 
   log.info(element.name)
  }
  webContents.getAllWebContents().forEach((item,index)=>{
    item.send('pageMessage', data);
  }) 
 });
///音频输出 

//下载资源
ipcMain.handle('downloadOffline', function(event,data){
  win.webContents.downloadURL(data+"/download/Project.zip");
  win.webContents.session.once('will-download', (event, item, webContents) => { 
    let directory= join(app.getPath('userData'), item.getFilename())
    console.log(item.getURL()) 
    console.log(directory)  
    // mkdirs(directory,function(){})
    //设置下载文件名 工程项目下载 
    item.setSavePath(directory)
    item.on('updated', (event, state) => {
      // 下载的事件
      if (state === "progressing") {
        if (!item.isPaused()) {
        //下载完成后传回进度
        win?.webContents.send("downing", 
          item.getReceivedBytes() * 100 / item.getTotalBytes())
        }
      }
    })
    item.once('done', (event, state) => {
      // 下载完成的事件
      if (state === "completed") {
        //下载完成后传回进度
        win?.webContents.send("downing", 100)

        fs.createReadStream(directory).pipe(unzip.Extract({ path: directory.replace(".zip","") }))  //解压时直接会覆盖重名文件
      }
    }) 
  }) 
}); 
//创建文件夹
function mkdirs(dirname:any, callback:any) { 
  fs.exists(dirname, function (exists:any) { 
      if (exists) { 
          callback(); 
      } else { 
          // console.log(path.dirname(dirname)); 
          mkdirs(path.dirname(dirname), function () { 
              fs.mkdir(dirname, callback); 
          }); 
      } 
  });
}
/////////////PY///////////////////
let pyProc:any;
// 启动flask server，通过python-shell 调用python脚本（开发调试阶段）
function startServer_PY() {
  var {PythonShell} = require('python-shell');

  let options = {
      mode: 'text',
      pythonPath: 'edu/Scripts/python'
  };

  PythonShell.run('./py/app.py',options, function (err, results) {
      if (err) throw err;
      // results is an array consisting of messages collected during execution
      console.log('response: ', results);
  });
}

// 启动flask server，通过子进程执行已经将python项目打包好的exe文件（打包阶段）
function startServer_EXE() {
  let script = path.join(process.env.DIST_ELECTRON, '../../pydist', '//app//app.exe') 
  // log.info(script)
  pyProc = require('child_process').execFile(script)
  if (pyProc != null) {
      console.log('flask server start success')
  }
}

// 停止flask server 函数
function stopServer() {
  if(pyProc!=null){
    pyProc.kill()
    console.log('kill flask server  success')
    pyProc = null
  } 
}
///////////////网络监测 
var isOnline = false;
var reconnectInterval = null;

function checkNetwork(callback) {
  if(!net){
    isOnline=true;
    win?.webContents.send("getNetworkStatus",isOnline); 
    return;
  }
  const socket = net.createConnection({
    host: 'www.thago.cn',
    port: 80
  }, () => {
    socket.end();
    isOnline=true;
    win?.webContents.send("getNetworkStatus",isOnline); 
    // callback(null, true);
    console.log('net ok...');
  });
 
  socket.on('error', () => {
    isOnline=false;
    // callback(null, false);
    win?.webContents.send("getNetworkStatus",isOnline);
    console.log('net error...');
  });
}
function startReconnectProcedure() {
  if(!isOnline&&!reconnectInterval){
    reconnectInterval = setInterval(() => {
      if (isOnline) {
        console.log('net success');
        clearInterval(reconnectInterval);
        reconnectInterval=null;
      } else {
        console.log('正在尝试重新连接...');
        // 这里可以添加重连代码，例如重启应用程序或者尝试重新加载窗口内容
        checkNetwork(null);
      }
    }, 5000); // 每3秒检查一次是否连接成功
  } 
}  
ipcMain.handle('checkNetwork', function(event,data){
  startReconnectProcedure(null);
});
checkNetwork(null);
startReconnectProcedure();  